package modelo.gestionPedidos;

import interfacesRemotas.InterfazPedido;

import java.io.Serializable;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;


import modelo.gestionCarta.Producto;

/**
 * Con esta clase representamos la petici�n de bebidas o platos por parte de un comensal 
 *(dentro de un determinado pedido).
 * 
 * @created 02-may-2007 17:25
 * @version 1.0
 * @author Enrique Menor Santos , Carmen Pastor Morales
 */

public class Consumicion implements Serializable
{
	/**
	 * 
	 */
	private static final long serialVersionUID = -3907154103105564404L;
	/**
	 * identificador del objeto junto con el codigo de pedido y el del producto, ya que es una entidad d�bil
	 */
	private int codConsumicion;
	/**
	 * nos indica el estado del pedido {"solicitado","pedir barra","retrasado","servido"}
	 */
	private int estado;
	/**
	 * nos indica el número de comensal al que pertenece esa consumición 
	 * (en la interfaz gráfica este atributo representa la SILLA del comensal).
	 */
	private int numComensal;
	/**
	 * observaciones que se han hecho sobre una consumición (con/sin sal, sin hielo, etc.).
	 */
	private String observaciones;
	/**
	 * Producto de la carta asociado a la consumicion
	 */
	private Producto producto; 
	/**
	 * Cadena que contiene la direccion ip donde se esta ejecutando el servidor RMI.
	 * Esto es necesario para la ejecucion de objetos remotos.
	 */
	private String ipServidorRMI;
	
	
	/**
	 * Constantes que representan el estado de los pedidos
	 */
	public static final int NINGUNO = 0;		//estado por defecto a no ser que se diga lo contrario
	public static final int SOLICITADO = 1;		//plato solicitado para su preparacion en cocina. 
												//OJO!! se pasará a este estado cuando la aplicacion de cocina envíe su notificacion
	public static final int EN_PREPARACION = 2;	//plato que ha sido extraido de la cola de espera de cocina y está siendo elaborado
	public static final int LISTO = 3;			//plato cocinado a espera de ser servido
	public static final int SERVIDO = 4;		//plato servido en mesa por cualquier camarero
	public static final int RETRASADO = 5;		//plato marcado como retrasado para no ser enviado a la cola de cocina
	
	
	/**
	 * 
	 * Constructor público: solo crea el objeto en memoria, no se accede a la base de datos
	 * PRECONDICION: se supone que el Producto que se pasa es un Producto de la BD
	 * @param p
	 * @param estado
	 * @param num
	 * @param obs
	 * 
	 */
	public Consumicion(Producto p, int estado,  int num, String obs, String ip)
	{
		
		//	esta comprobación no es necesaria pq la GUI garantiza los valores corractos
		 
		if(estado >= NINGUNO && estado <= RETRASADO)
			 this.estado=estado;
		else
			this.estado=NINGUNO;
			
		if (num>0)
			this.numComensal = num;
		else
			this.numComensal=0;		//se apunta la consumicion a todos los comensales
		this.observaciones=obs;
		this.producto=p;
		this.ipServidorRMI=ip;
					
	}
	/**
	 * 
	 * Constructor público: Este constructor se utiliza desde el lado servidor 
	 * para almacenar en memoria los datos de una consumicion extraidos de la bd.
	 * Este constructor será ejecutado en el Servidor, por lo q el atributo ipServidorRMI será creado de forma automática
	 * usando la clase InetAdress.
	 * @param p
	 * @param estado
	 * @param num
	 * @param obs
	 * @param cod
	 */
	
public Consumicion(int cod,  int estado,  int num, String obs,Producto p){
		this.codConsumicion=cod;
		this.estado=estado;
		this.numComensal=num;
		this.observaciones=obs;
		this.producto=p;	
		try {
			this.ipServidorRMI = InetAddress.getLocalHost().getHostAddress();
		} catch (UnknownHostException e) {
			//e.printStackTrace();
			System.err.println("Error en la clase Pedido al crear el pedido: " + e.getMessage());
		}
	}
	/**
	 * Este método crea la consumicion en la base de datos de forma permanente. 
	 * Se comprueba que  existe la seccion y que contiene al producto.
	 * (Se supone que esta comprobacion se realiza en la GUI)
	 * En caso contrario, o si ocurre un error al acceder a la BD, se devuelve falso.
	 * @param idPedido
	 * @return cierto si se consigue crear la Consumicion en la BD. en caso contrario devuelve falso
	 */
	public boolean crearConsumicion(int idPedido)
	{
		boolean creada=false;
		InterfazPedido ap;
		try {
			ap=(InterfazPedido)Naming.lookup("//"+this.ipServidorRMI+"/AccesoPedido");
			creada=ap.insertConsumicion(this.producto.consultarIdProducto(),idPedido,this.estado,this.numComensal,this.observaciones);			
		}catch (RemoteException e) {
			System.err.println("Error remoto en la clase Consumicion al crear la consumicion: " + e.getMessage());
		} catch (MalformedURLException e) {
			//e.printStackTrace();
			System.err.println("Error URL no valida en la clase Consumicion al crear la consumicion: " + e.getMessage());
		} catch (NotBoundException e) {
			//e.printStackTrace();
			System.err.println("Error Not Bound en la clase Consumicion al crear el consumicion: " + e.getMessage());
		}
		return creada;
	}
	/**
	 * Este método busca y elimina la consumición de la BD..
	 * @return cierto si se ha eliminado con éxito, falso en caso contrario
	 */
	public boolean eliminarConsumicion()
	{
		InterfazPedido ap;
		boolean borrada=false;
		
		try {
			ap=(InterfazPedido)Naming.lookup("//"+this.ipServidorRMI+"/AccesoPedido");
			borrada=ap.deleteConsumicion(this.codConsumicion);
		} catch (RemoteException e) {
//			e.printStackTrace();
			System.err.println("Error remoto en la clase Consumicion al eliminar la consumicion: " + e.getMessage());
		} catch (MalformedURLException e) {
//			e.printStackTrace();
			System.err.println("Error URL no valida en la clase Consumicion al eliminar la consumicion: " + e.getMessage());
		} catch (NotBoundException e) {
//			e.printStackTrace();
			System.err.println("Error Not Bound en la clase Consumicion al eliminar el consumicion: " + e.getMessage());
		}
		return borrada;
	}
	/**
	 * Este método actualiza TODOS los campos de la consumicion en la BD
	 * @return
	 */
	public boolean actualizarConsumicion()
	{
		//int idConsu, int estado, int numComensal, String observaciones, Producto p
		InterfazPedido ap;
		boolean borrada=false;
		try {
			ap=(InterfazPedido)Naming.lookup("//"+this.ipServidorRMI+"/AccesoPedido");
			borrada=ap.updateConsumicion(this.codConsumicion, this.estado, this.numComensal, this.observaciones,this.producto);
		} catch (RemoteException e) {
//			e.printStackTrace();
			System.err.println("Error remoto en la clase Consumicion al actualizar la consumicion: " + e.getMessage());			
		} catch (MalformedURLException e) {
//			e.printStackTrace();
			System.err.println("Error URL no valida en la clase Consumicion al actualizar la consumicion: " + e.getMessage());
		} catch (NotBoundException e) {
//			e.printStackTrace();
			System.err.println("Error Not Bound en la clase Consumicion al actualizar el consumicion: " + e.getMessage());
		}
		return borrada;
	}
	/**
	 * OJO!! no existe setCodConsumicion
	 * @return el código de la consumicion
	 */
	public int getCodConsumicion()
	{
		return this.codConsumicion;
	}
	/**
	 * @return el estado de la consumicion
	 */
	public int getEstado() {
		return estado;
	}
	/**
	 * //TODO: este método debería de avisar a la aplicacion de cocina en la 3º iteracion 
	 * OJO!! Para hacer efectivos los cambios en la BD hay que llamar a 'actualizarConsumicion();'
	 * @param estado el estado a establecer
	 */
	public void setEstado(int estado) {
		//TODO: para el subsistema de cocina, habría que comprobar si el estado es "LISTO" y en ese caso sacar una alarma por pantalla de todas las PDAs
		if(estado >= NINGUNO && estado <= RETRASADO)
			 this.estado=estado;
		else
			this.estado=NINGUNO;
	}
	/**
	 * @return el numero de comensal asociado a la consumicion
	 */
	public int getNumComensal() {
		return numComensal;
	}
	/**
	 * OJO!! Para hacer efectivos los cambios en la BD hay que llamar a 'actualizarConsumicion();'
	 * @param establece el numero de comensal asociado a la consumicion
	 */
	public void setNumComensal(int numComensal) {
		this.numComensal = numComensal;
		
	}
	/**
	 * @return las observaciones de la consumicion
	 */
	public String getObservaciones() {
		return observaciones;
	}
	/**
	 * OJO!! Para hacer efectivos los cambios en la BD hay que llamar a 'actualizarConsumicion();'
	 * @param  establece las observaciones asociadas a la consumicion
	 */
	public void setObservaciones(String observaciones) {
		this.observaciones = observaciones;
		
	}
	/**
	 * @return el producto asociado a la consumicion
	 */
	public Producto getProducto() {
		return producto;
	}
	/**
	 * Método que modifica el producto.
	 * OJO!! Para hacer efectivos los cambios en la BD hay que llamar a 'actualizarConsumicion();'
	 * Se supone que el producto pertenece al sistema la GUI se encarga de eso
	 * @param p
	 */
	public void setProducto(Producto p)
	{
		if (p!= null)
			this.producto=p;
	}
	/**
	 * Redefinicion del toString
	 */
	public String toString()
	{
		String s = "";
		String e = "";
		switch(this.estado)
		{
			case(0):e="ninguno";break;
			case(1):e="solicitado";break;
			case(2):e="en preparacion";break;
			case(3):e="listo";break;
			case(4):e="servido";break;
			case(5):e="retrasado";break;
		}
		if (this.producto!=null)
		{
			s=s+"[ PRODUCTO: "+this.producto.consultarNombreProducto()+
			", COMENSALl: "+this.getNumComensal()+
			", ESTADO: "+e+
			", OBSERVACIONES: "+this.observaciones+"]";
		}
		
		return  s;
	}
	
}
